import csv
import filecmp
import hashlib
# from PIL.ImageQt import ImageQt  # 如果需要处理 QPixmap 转 QImage
import os
import shutil
import uuid
import zipfile
from urllib.request import urlretrieve

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QTextDocument, QPixmap
from PyQt5.QtPrintSupport import QPrinter
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QHBoxLayout,
                             QTableWidget, QTableWidgetItem, QPushButton,
                             QLabel, QLineEdit, QTextEdit, QComboBox, QSpinBox,
                             QCheckBox, QRadioButton, QButtonGroup, QGroupBox,
                             QFileDialog, QHeaderView, QDialog, QProgressDialog, QStackedWidget,
                             QInputDialog, QFormLayout, QScrollArea, QFrame, QGridLayout)
from PyQt5.QtWidgets import QMessageBox
from docx import Document
from docx.oxml.ns import qn
from docx.shared import Inches

from database import get_db_connection, backup_database, restore_database
from export_dialog import ExportDialog
from image_dialog import ImageButton
from share_dialog import ShareDialog
from web_sharing import SharingServer


class QuestionTable(QTableWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setColumnCount(6)
        self.setHorizontalHeaderLabels(["ID", "类型", "题目", "难度", "分类", "收藏"])
        self.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch)
        self.verticalHeader().setVisible(False)
        self.setSelectionBehavior(QTableWidget.SelectRows)
        self.setSelectionMode(QTableWidget.ExtendedSelection)
        self.setEditTriggers(QTableWidget.NoEditTriggers)

    def add_question(self, question):
        row = self.rowCount()
        self.insertRow(row)
        self.setItem(row, 0, QTableWidgetItem(question['id']))
        item = QTableWidgetItem(question['question_type'])
        item.setTextAlignment(Qt.AlignCenter)
        self.setItem(row, 1, item)
        # 限制题目显示长度
        content = question['content']
        if len(content) > 50:
            content = content[:50] + "..."
        self.setItem(row, 2, QTableWidgetItem(content))
        self.setItem(row, 3, QTableWidgetItem('★' * question['difficulty']))
        self.setItem(row, 4, QTableWidgetItem(question['category']))

        if question['is_favorite']:
            favorite_item = QTableWidgetItem("是")
            favorite_item.setTextAlignment(Qt.AlignCenter)
            self.setItem(row, 5, favorite_item)
        else:
            favorite_item = QTableWidgetItem("否")
            favorite_item.setTextAlignment(Qt.AlignCenter)
            self.setItem(row, 5, favorite_item)


class QuestionEditWidget(QWidget):
    def __init__(self, main_window):  # 接收main_window参数
        super().__init__()
        self.main_window = main_window  # 保存main_window引用
        self.current_id = None
        self.fields_locked = False  # 锁定状态
        self.locked_values = {}  # 保存锁定时的值
        self.setup_ui()

    def setup_ui(self):
        # 添加统一锁定按钮
        self.lock_btn = QPushButton("锁定当前设置")
        self.lock_btn.setFixedWidth(100)
        self.lock_btn.setObjectName("lockButton")
        self.lock_btn.setCheckable(True)
        self.lock_btn.setIcon(QIcon.fromTheme("object-locked"))
        self.lock_btn.setToolTip("锁定当前题目类型、标签和分类")
        self.lock_btn.toggled.connect(self.toggle_lock)

        layout = QVBoxLayout()
        # 题目类型选择
        self.type_combo = QComboBox()
        self.type_combo.addItems(["填空题", "选择题", "判断题", "综合题"])
        self.type_combo.currentTextChanged.connect(self.on_type_changed)

        # 题目内容
        self.content_edit = QTextEdit()
        self.content_edit.setPlaceholderText("请输入题目内容...")

        # 题目图片
        self.content_image_btn = ImageButton()

        # 难度选择
        self.difficulty_spin = QSpinBox()
        self.difficulty_spin.setRange(1, 5)
        self.difficulty_spin.setValue(3)

        # 标签
        self.tags_edit = QLineEdit()
        self.tags_edit.setPlaceholderText("多个标签用逗号分隔")

        # 分类
        self.category_edit = QLineEdit()
        self.category_edit.setPlaceholderText("输入题目分类")

        # 收藏
        self.favorite_check = QCheckBox("收藏此题")

        # 答案部分 - 动态变化
        self.answer_stack = QWidget()
        self.answer_layout = QVBoxLayout(self.answer_stack)

        # 填空题答案
        self.fill_blank_answer_edit = QTextEdit()
        self.fill_blank_answer_edit.setPlaceholderText("多个填空答案用|分隔")

        # 选择题选项
        self.choice_options = []
        self.choice_buttons = []
        self.choice_answer_edit = QLineEdit()
        self.choice_answer_edit.setReadOnly(True)

        choice_options_group = QGroupBox()
        choice_options_layout = QGridLayout()  # 改为网格布局

        for i in range(8):
            # 计算行列位置
            row = i // 2  # 每行放2个选项
            column = i % 2

            # 创建选项容器
            option_container = QHBoxLayout()

            checkbox = QCheckBox(chr(65 + i))
            checkbox.toggled.connect(self.update_choice_answer)
            text_edit = QLineEdit()
            text_edit.setPlaceholderText(f"选项{chr(65 + i)}内容")
            text_edit.textChanged.connect(self.update_choice_answer)

            self.choice_buttons.append(checkbox)
            self.choice_options.append(text_edit)

            # 添加间距和边距
            option_container.addWidget(checkbox)
            option_container.addWidget(text_edit)
            option_container.setContentsMargins(5, 2, 5, 2)
            option_container.setSpacing(8)

            # 将容器添加到网格布局
            choice_options_layout.addLayout(option_container, row, column)

        # 设置列宽比例
        choice_options_layout.setColumnStretch(0, 1)
        choice_options_layout.setColumnStretch(1, 1)
        choice_options_layout.setHorizontalSpacing(20)  # 列间距
        choice_options_group.setLayout(choice_options_layout)
        # 判断题选项
        self.judgement_group = QButtonGroup()
        self.judgement_true = QRadioButton("正确")
        self.judgement_false = QRadioButton("错误")
        self.judgement_group.addButton(self.judgement_true)
        self.judgement_group.addButton(self.judgement_false)
        self.judgement_group.buttonToggled.connect(self.update_judgement_answer)

        # 修改后代码
        judgement_layout = QHBoxLayout()
        judgement_layout.setAlignment(Qt.AlignLeft)  # 设置左对齐
        judgement_layout.setAlignment(Qt.AlignTop)  # 设置上对齐
        judgement_layout.addWidget(self.judgement_true)
        judgement_layout.addWidget(self.judgement_false)
        judgement_layout.addStretch()  # 添加伸缩项将内容推向左侧
        judgement_layout.setContentsMargins(0, 0, 0, 0)  # 去除边距

        # 综合题答案
        self.comprehensive_answer_edit = QTextEdit()
        self.comprehensive_answer_edit.setPlaceholderText("请输入综合题答案...")

        # 答案图片
        self.answer_image_btn = ImageButton()

        # 备注
        # self.notes_edit = QTextEdit()
        self.notes_edit = QLineEdit()
        self.notes_edit.setPlaceholderText("可添加备注信息...")

        # 按钮区域
        self.save_btn = QPushButton("保存")
        self.save_btn.clicked.connect(self.save_question)
        self.clear_btn = QPushButton("清空")
        self.clear_btn.clicked.connect(self.clear_form)
        # 添加返回按钮
        self.back_btn = QPushButton("返回")
        self.back_btn.clicked.connect(self.main_window.show_list)

        # 表单布局
        form_layout = QVBoxLayout()

        tags_category_layout = QHBoxLayout()
        tags_category_layout.addWidget(QLabel("标签:"))
        tags_category_layout.addWidget(self.tags_edit)
        tags_category_layout.addWidget(QLabel("分类:"))
        tags_category_layout.addWidget(self.category_edit)
        form_layout.addLayout(tags_category_layout)

        type_diff_layout = QHBoxLayout()
        type_diff_layout.addWidget(QLabel("题目类型:"))
        type_diff_layout.addWidget(self.type_combo)
        type_diff_layout.addWidget(QLabel("难度:"))
        type_diff_layout.addWidget(self.difficulty_spin)
        type_diff_layout.addWidget(QLabel())
        type_diff_layout.addWidget(self.favorite_check)
        type_diff_layout.addWidget(QLabel())
        type_diff_layout.addWidget(QLabel())
        type_diff_layout.addWidget(QLabel())
        form_layout.addLayout(type_diff_layout)
        # 题目内容
        form_layout.addWidget(QLabel("题目内容:"))
        form_layout.addWidget(self.content_edit)

        # 题目图片
        form_layout.addWidget(QLabel("题目图片:"))
        form_layout.addWidget(self.content_image_btn)

        # 答案部分
        self.answer_label = QLabel("答案:")
        form_layout.addWidget(self.answer_label)

        # 动态答案区域
        self.fill_blank_answer = QWidget()
        fill_blank_layout = QVBoxLayout(self.fill_blank_answer)
        fill_blank_layout.addWidget(self.fill_blank_answer_edit)

        self.choice_answer = QWidget()
        choice_answer_layout = QVBoxLayout(self.choice_answer)
        choice_answer_layout.addWidget(choice_options_group)
        choice_answer_layout.addWidget(QLabel("答案:"))
        choice_answer_layout.addWidget(self.choice_answer_edit)

        self.judgement_answer = QWidget()
        judgement_answer_layout = QVBoxLayout(self.judgement_answer)
        judgement_answer_layout.addLayout(judgement_layout)

        self.comprehensive_answer = QWidget()
        comprehensive_answer_layout = QVBoxLayout(self.comprehensive_answer)
        comprehensive_answer_layout.addWidget(self.comprehensive_answer_edit)
        # 布局2
        self.answer_stack = QStackedWidget()
        self.answer_stack.addWidget(self.fill_blank_answer)
        self.answer_stack.addWidget(self.choice_answer)
        self.answer_stack.addWidget(self.judgement_answer)
        self.answer_stack.addWidget(self.comprehensive_answer)

        form_layout.addWidget(self.answer_stack)

        # 答案图片
        form_layout.addWidget(QLabel("答案图片:"))
        form_layout.addWidget(self.answer_image_btn)

        # 备注
        form_layout.addWidget(QLabel("备注:"))
        form_layout.addWidget(self.notes_edit)

        # 按钮
        button_layout = QHBoxLayout()
        button_layout.addWidget(self.save_btn)
        button_layout.addWidget(self.clear_btn)
        button_layout.addWidget(self.back_btn)
        form_layout.addLayout(button_layout)

        layout.addLayout(form_layout)
        self.setLayout(layout)
        # 将锁定按钮添加到表单顶部
        form_layout.insertWidget(0, self.lock_btn)

        # 初始化显示填空题
        self.on_type_changed("填空题")

    def on_type_changed(self, qtype):
        if qtype == "填空题":
            self.answer_stack.setCurrentWidget(self.fill_blank_answer)
            self.answer_label.setText("答案:")
        elif qtype == "选择题":
            self.answer_stack.setCurrentWidget(self.choice_answer)
            self.answer_label.setText("选项:")
            self.choice_answer_edit.setPlaceholderText("请填充并勾选选项自动填充答案...")
        elif qtype == "判断题":
            self.answer_stack.setCurrentWidget(self.judgement_answer)
            self.answer_label.setText("答案:")
        elif qtype == "综合题":
            self.answer_stack.setCurrentWidget(self.comprehensive_answer)
            self.answer_label.setText("答案:")

    def toggle_lock(self, checked):
        """切换锁定状态"""
        self.fields_locked = checked

        if checked:
            # 锁定当前设置
            self.locked_values = {
                'question_type': self.type_combo.currentText(),
                'tags': self.tags_edit.text(),
                'category': self.category_edit.text()
            }
            self.lock_btn.setText("已锁定设置")
            self.lock_btn.setStyleSheet("background-color: #FAEBD7;")
            self.type_combo.setDisabled(True)
            self.type_combo.setStyleSheet("background-color: #FAEBD7;")
            self.tags_edit.setDisabled(True)
            self.tags_edit.setStyleSheet("background-color: #FAEBD7;")
            self.category_edit.setDisabled(True)
            self.category_edit.setStyleSheet("background-color: #FAEBD7;")
        else:
            # 解除锁定
            self.locked_values = {}
            self.lock_btn.setText("锁定当前设置")
            self.lock_btn.setStyleSheet("")
            self.type_combo.setStyleSheet("")
            self.type_combo.setDisabled(False)
            self.tags_edit.setStyleSheet("")
            self.tags_edit.setDisabled(False)
            self.category_edit.setStyleSheet("")
            self.category_edit.setDisabled(False)

    def update_choice_answer(self):
        answers = []
        for i, checkbox in enumerate(self.choice_buttons):
            if checkbox.isChecked():
                text = self.choice_options[i].text().strip()
                if text:
                    answers.append(chr(65 + i))

        self.choice_answer_edit.setText("".join(answers))

    def update_judgement_answer(self, button, checked):
        if checked:
            if button == self.judgement_true:
                self.choice_answer_edit.setText("正确")
            else:
                self.choice_answer_edit.setText("错误")

    def clear_form(self):
        self.current_id = None
        self.type_combo.setCurrentIndex(0)
        self.content_edit.clear()
        self.content_image_btn.set_image("")
        self.difficulty_spin.setValue(3)
        self.tags_edit.clear()
        self.category_edit.clear()
        self.favorite_check.setChecked(False)
        self.fill_blank_answer_edit.clear()
        for option in self.choice_options:
            option.clear()
        for checkbox in self.choice_buttons:
            checkbox.setChecked(False)
        self.judgement_group.setExclusive(False)
        self.judgement_true.setChecked(False)
        self.judgement_false.setChecked(False)
        self.judgement_group.setExclusive(True)
        self.comprehensive_answer_edit.clear()
        self.answer_image_btn.set_image("")
        self.notes_edit.clear()
        # 恢复锁定的字段值
        if self.fields_locked:
            self.type_combo.setCurrentText(self.locked_values['question_type'])
            self.tags_edit.setText(self.locked_values['tags'])
            self.category_edit.setText(self.locked_values['category'])
            self.on_type_changed(self.locked_values['question_type'])
        else:
            self.type_combo.setCurrentIndex(0)
            self.tags_edit.clear()
            self.category_edit.clear()

    def load_question(self, question):
        self.current_id = question['id']
        self.type_combo.setCurrentText(question['question_type'])
        self.content_edit.setPlainText(question['content'])

        if question['content_image']:
            self.content_image_btn.set_image(question['content_image'])

        self.difficulty_spin.setValue(question['difficulty'])
        self.tags_edit.setText(question['tags'])
        self.category_edit.setText(question['category'])
        self.favorite_check.setChecked(question['is_favorite'])

        if question['question_type'] == "填空题":
            self.fill_blank_answer_edit.setPlainText(question['answer'])
        elif question['question_type'] == "选择题":
            # 解析选项
            options = question['answer'].split('|')
            answer = options[-1] if options else ""
            options = options[:-1] if options else []

            for i, option in enumerate(options[:6]):
                self.choice_options[i].setText(option)

            # 设置选中状态
            for checkbox in self.choice_buttons:
                checkbox.setChecked(False)

            for char in answer:
                idx = ord(char.upper()) - ord('A')
                if 0 <= idx < len(self.choice_buttons):
                    self.choice_buttons[idx].setChecked(True)
        elif question['question_type'] == "判断题":
            if question['answer'] == "正确":
                self.judgement_true.setChecked(True)
            else:
                self.judgement_false.setChecked(True)
        elif question['question_type'] == "综合题":
            self.comprehensive_answer_edit.setPlainText(question['answer'])

        if question['answer_image']:
            self.answer_image_btn.set_image(question['answer_image'])

        self.notes_edit.setText(question['notes'] or "")

    def save_question(self):
        question_type = self.type_combo.currentText()
        content = self.content_edit.toPlainText().strip()

        if not content:
            QMessageBox.warning(self, "警告", "题目内容不能为空!")
            return

        # 获取答案
        answer = ""
        if question_type == "填空题":
            answer = self.fill_blank_answer_edit.toPlainText().strip()
            if not answer:
                QMessageBox.warning(self, "警告", "填空题答案不能为空!")
                return
        elif question_type == "选择题":
            # 检查是否有选项内容
            has_options = False
            for option in self.choice_options:
                if option.text().strip():
                    has_options = True
                    break

            if not has_options:
                QMessageBox.warning(self, "警告", "至少需要一个选项!")
                return

            # 检查是否选择了答案
            answer = self.choice_answer_edit.text().strip()
            if not answer:
                QMessageBox.warning(self, "警告", "请选择至少一个答案!")
                return

            # 格式化为: 选项A|选项B|选项C|答案
            options = []
            for i, option in enumerate(self.choice_options):
                text = option.text().strip()
                if text:
                    options.append(text)

            answer = "|".join(options) + "|" + answer
        elif question_type == "判断题":
            answer = self.choice_answer_edit.text().strip()
            if not answer:
                QMessageBox.warning(self, "警告", "请选择正确或错误!")
                return
        elif question_type == "综合题":
            answer = self.comprehensive_answer_edit.toPlainText().strip()
            if not answer:
                QMessageBox.warning(self, "警告", "综合题答案不能为空!")
                return

        # 处理图片
        content_image_path = self.content_image_btn.image_path
        answer_image_path = self.answer_image_btn.image_path

        # 生成题目唯一ID和MD5
        question_id = self.current_id if self.current_id else str(uuid.uuid4())
        md5 = hashlib.md5((content + answer).encode('utf-8')).hexdigest()

        # 检查是否已存在相同的题目
        conn = get_db_connection()
        cursor = conn.cursor()

        if not self.current_id:  # 新增题目
            cursor.execute("SELECT id FROM questions WHERE md5=?", (md5,))
            if cursor.fetchone():
                QMessageBox.warning(self, "警告", "已存在相同的题目!")
                conn.close()
                return

        # 创建图片目录
        image_dir = os.path.join("data", "images", question_id)
        if not os.path.exists(image_dir):
            os.makedirs(image_dir)

        # 处理题目图片
        saved_content_image = ""
        if content_image_path and os.path.exists(content_image_path):
            # 只有当图片不在目标目录时才复制
            ext = os.path.splitext(content_image_path)[1]
            new_path = os.path.join(image_dir, f"content{ext}")

            # 检查是否需要复制（路径不同且文件不同）
            if not os.path.exists(new_path) or not filecmp.cmp(content_image_path, new_path, shallow=False):
                shutil.copy2(content_image_path, new_path)
            saved_content_image = new_path

        # 处理答案图片
        saved_answer_image = ""
        if answer_image_path and os.path.exists(answer_image_path):
            ext = os.path.splitext(answer_image_path)[1]
            new_path = os.path.join(image_dir, f"answer{ext}")

            # 检查是否需要复制（路径不同且文件不同）
            if not os.path.exists(new_path) or not filecmp.cmp(answer_image_path, new_path, shallow=False):
                shutil.copy2(answer_image_path, new_path)
            saved_answer_image = new_path

        # 准备题目数据
        question_data = {
            'id': question_id,
            'question_type': question_type,
            'content': content,
            'content_image': saved_content_image,
            'difficulty': self.difficulty_spin.value(),
            'tags': self.tags_edit.text().strip(),
            'category': self.category_edit.text().strip(),
            'answer': answer,
            'answer_image': saved_answer_image,
            'notes': self.notes_edit.text().strip(),
            'is_favorite': 1 if self.favorite_check.isChecked() else 0,
            'md5': md5
        }

        # 保存到数据库
        if self.current_id:  # 更新
            cursor.execute('''
                UPDATE questions SET 
                    question_type=?, content=?, content_image=?, difficulty=?, 
                    tags=?, category=?, answer=?, answer_image=?, notes=?, 
                    is_favorite=?, md5=?, updated_at=CURRENT_TIMESTAMP
                WHERE id=?
            ''', (
                question_data['question_type'], question_data['content'],
                question_data['content_image'], question_data['difficulty'],
                question_data['tags'], question_data['category'],
                question_data['answer'], question_data['answer_image'],
                question_data['notes'], question_data['is_favorite'],
                question_data['md5'], question_data['id']
            ))
        else:  # 新增
            cursor.execute('''
                INSERT INTO questions (
                    id, question_type, content, content_image, difficulty, 
                    tags, category, answer, answer_image, notes, 
                    is_favorite, md5
                ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            ''', (
                question_data['id'], question_data['question_type'],
                question_data['content'], question_data['content_image'],
                question_data['difficulty'], question_data['tags'],
                question_data['category'], question_data['answer'],
                question_data['answer_image'], question_data['notes'],
                question_data['is_favorite'], question_data['md5']
            ))

        conn.commit()
        conn.close()

        QMessageBox.information(self, "成功", "题目保存成功!")
        self.clear_form()
        self.main_window.refresh_question_list()  # 使用main_window引用


class QuestionListWidget(QWidget):
    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window
        self.sharing_server = SharingServer()
        self.sharing_server.sharing_started.connect(self.on_sharing_started)
        self.sharing_server.sharing_stopped.connect(self.on_sharing_stopped)
        self.setup_ui()

    def setup_ui(self):

        layout = QVBoxLayout()

        # 搜索和过滤区域
        filter_layout = QHBoxLayout()

        self.search_edit = QLineEdit()
        self.search_edit.setPlaceholderText("搜索题目内容...")
        self.search_edit.setMinimumWidth(200)
        self.search_edit.setMaximumWidth(400)
        self.type_combo = QComboBox()
        self.type_combo.addItem("所有类型", "")
        self.type_combo.addItem("填空题", "填空题")
        self.type_combo.addItem("选择题", "选择题")
        self.type_combo.addItem("判断题", "判断题")
        self.type_combo.addItem("综合题", "综合题")

        self.difficulty_combo = QComboBox()
        self.difficulty_combo.addItem("所有难度", 0)
        for i in range(1, 6):
            self.difficulty_combo.addItem(f"{i}星难度", i)

        self.category_combo = QComboBox()
        self.category_combo.addItem("所有分类", "")

        self.tags_edit = QLineEdit()
        self.tags_edit.setPlaceholderText("标签筛选,用逗号分隔")
        self.tags_edit.setMinimumWidth(200)
        self.tags_edit.setMaximumWidth(400)

        self.favorite_check = QCheckBox("只显示收藏")

        self.search_btn = QPushButton("搜索")
        self.search_btn.clicked.connect(self.search_questions)

        filter_layout.addWidget(self.search_edit)
        filter_layout.addWidget(QLabel("类型:"))
        filter_layout.addWidget(self.type_combo)
        filter_layout.addWidget(QLabel("难度:"))
        filter_layout.addWidget(self.difficulty_combo)
        filter_layout.addWidget(QLabel("分类:"))
        filter_layout.addWidget(self.category_combo)
        filter_layout.addWidget(QLabel("标签:"))
        filter_layout.addWidget(self.tags_edit)
        filter_layout.addWidget(self.favorite_check)
        filter_layout.addWidget(self.search_btn)

        # 表格和分页
        self.table = QuestionTable()

        # 分页控件
        page_layout = QHBoxLayout()

        self.prev_btn = QPushButton("上一页")
        self.prev_btn.clicked.connect(self.prev_page)

        self.page_label = QLabel("1/1")
        self.page_label.setAlignment(Qt.AlignCenter)

        self.next_btn = QPushButton("下一页")
        self.next_btn.clicked.connect(self.next_page)

        self.page_size_combo = QComboBox()
        self.page_size_combo.addItems(["10", "20", "50", "100"])
        self.page_size_combo.setCurrentIndex(1)
        self.page_size_combo.currentIndexChanged.connect(self.change_page_size)

        page_layout.addWidget(self.prev_btn)
        page_layout.addWidget(self.page_label)
        page_layout.addWidget(self.next_btn)
        page_layout.addStretch()
        page_layout.addWidget(QLabel("每页:"))
        page_layout.addWidget(self.page_size_combo)

        # 操作按钮
        button_layout = QHBoxLayout()

        self.add_btn = QPushButton("新增")
        self.add_btn.clicked.connect(self.add_question)

        self.edit_btn = QPushButton("编辑")
        self.edit_btn.clicked.connect(self.edit_question)

        self.delete_btn = QPushButton("删除")
        self.delete_btn.clicked.connect(self.delete_questions)

        self.export_btn = QPushButton("导出")
        self.export_btn.setStyleSheet("""
            QPushButton {
                background-color: #9370DB;
                border: 1px solid #888;  /* 可选：添加边框增强视觉效果 */
            }
            /* 悬停时颜色略微变深 */
            QPushButton:hover {
                background-color: #E6E6FA;
            }
        """)
        self.export_btn.clicked.connect(self.export_questions)

        self.import_btn = QPushButton("导入")
        self.import_btn.setStyleSheet("""
            QPushButton {
                background-color: #9370DB;
                border: 1px solid #888;  /* 可选：添加边框增强视觉效果 */
            }
            /* 悬停时颜色略微变深 */
            QPushButton:hover {
                background-color: #E6E6FA;
            }
        """)
        self.import_btn.clicked.connect(self.import_questions)

        self.backup_btn = QPushButton("备份")
        self.backup_btn.setStyleSheet("""
            QPushButton {
                background-color: #CD5C5C;
                border: 1px solid #888;  /* 可选：添加边框增强视觉效果 */
            }
            /* 悬停时颜色略微变深 */
            QPushButton:hover {
                background-color: #F08080;
            }
        """)
        self.backup_btn.clicked.connect(self.backup_data)

        self.restore_btn = QPushButton("恢复")
        self.restore_btn.setStyleSheet("""
            QPushButton {
                background-color: #CD5C5C;
                border: 1px solid #888;  /* 可选：添加边框增强视觉效果 */
            }
            /* 悬停时颜色略微变深 */
            QPushButton:hover {
                background-color: #F08080;
            }
        """)
        self.restore_btn.clicked.connect(self.restore_data)

        # # 在QuestionListWidget的setup_ui方法中添加查看按钮
        # self.detail_btn = QPushButton("查看详情")
        # self.detail_btn.clicked.connect(self.show_question_detail)
        #
        # # 在按钮布局中添加
        # button_layout.addWidget(self.detail_btn)
        # 添加双击查看功能
        self.table.doubleClicked.connect(self.show_question_detail)

        button_layout.addWidget(self.add_btn)
        button_layout.addWidget(self.edit_btn)
        button_layout.addWidget(self.delete_btn)
        button_layout.addStretch()
        button_layout.addWidget(self.export_btn)
        button_layout.addWidget(self.import_btn)
        button_layout.addStretch()
        button_layout.addWidget(self.backup_btn)
        button_layout.addWidget(self.restore_btn)

        layout.addLayout(filter_layout)
        layout.addWidget(self.table)
        layout.addLayout(page_layout)
        layout.addLayout(button_layout)

        self.setLayout(layout)

        # 分页变量
        self.current_page = 1
        self.page_size = 20
        self.total_pages = 1
        self.total_records = 0

        # 加载初始数据
        self.load_categories()
        self.search_questions()

        # 在按钮区域添加导出按钮
        self.export_all_btn = QPushButton("导出试题到文档")
        self.export_all_btn.setStyleSheet("""
            QPushButton {
                background-color: #F4A460;
                border: 1px solid #888;  /* 可选：添加边框增强视觉效果 */
            }
            /* 悬停时颜色略微变深 */
            QPushButton:hover {
                background-color: #FFDAB9;
            }
        """)
        self.export_all_btn.setIcon(QIcon.fromTheme("document-export"))
        self.export_all_btn.clicked.connect(self.export_all_questions)
        button_layout.addWidget(self.export_all_btn)
        # 添加共享相关控件
        self.share_btn = QPushButton("WEB分享")
        self.share_btn.setStyleSheet("""
            QPushButton {
                background-color: #808A87;
                border: 1px solid #888;  /* 可选：添加边框增强视觉效果 */
            }
            /* 悬停时颜色略微变深 */
            QPushButton:hover {
                background-color: #C0C0C0;
            }
        """)
        self.share_btn.setIcon(QIcon.fromTheme("network-server"))
        self.share_btn.clicked.connect(self.start_sharing_export)

        self.sharing_label = QLabel()
        self.sharing_label.setOpenExternalLinks(True)
        self.sharing_label.hide()

        self.stop_sharing_btn = QPushButton("停止共享")
        self.stop_sharing_btn.setStyleSheet("""
            QPushButton {
                background-color: #808A87;
                border: 1px solid #888;  /* 可选：添加边框增强视觉效果 */
            }
            /* 悬停时颜色略微变深 */
            QPushButton:hover {
                background-color: #C0C0C0;
            }
        """)
        self.stop_sharing_btn.setIcon(QIcon.fromTheme("process-stop"))
        self.stop_sharing_btn.clicked.connect(self.sharing_server.stop_sharing)
        self.stop_sharing_btn.hide()

        self.url_import_btn = QPushButton("WEB接收")
        self.url_import_btn.setStyleSheet("""
            QPushButton {
                background-color: #808A87;
                border: 1px solid #888;  /* 可选：添加边框增强视觉效果 */
            }
            /* 悬停时颜色略微变深 */
            QPushButton:hover {
                background-color: #C0C0C0;
            }
        """)
        self.url_import_btn.setIcon(QIcon.fromTheme("network-workgroup"))
        self.url_import_btn.clicked.connect(self.import_from_url)

        # 添加到布局
        button_layout.addWidget(self.share_btn)
        button_layout.addWidget(self.url_import_btn)

        sharing_layout = QHBoxLayout()
        sharing_layout.addWidget(self.sharing_label)
        sharing_layout.addWidget(self.stop_sharing_btn)
        sharing_layout.addStretch()
        layout.addLayout(sharing_layout)

    def show_question_detail(self):
        selected = self.table.selectedItems()
        if not selected:
            QMessageBox.warning(self, "警告", "请选择要查看的题目!")
            return

        row = selected[0].row()
        question_id = self.table.item(row, 0).text()

        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM questions WHERE id=?", (question_id,))
        row = cursor.fetchone()
        conn.close()

        if row:
            question = {
                'id': row[0],
                'question_type': row[1],
                'content': row[2],
                'content_image': row[3],
                'difficulty': row[4],
                'tags': row[5],
                'category': row[6],
                'answer': row[7],
                'answer_image': row[8],
                'notes': row[9],
                'is_favorite': row[10]
            }
            dialog = QuestionDetailDialog(question, self)
            dialog.exec_()

    def start_sharing_export(self):
        """导出并共享文件"""
        # 创建临时导出文件
        temp_dir = os.path.join("temp", "shared_export")
        os.makedirs(temp_dir, exist_ok=True)
        zip_path = os.path.join(temp_dir, "questions_export.zip")

        # 导出到ZIP
        if not self.export_questions_to_zip(zip_path):
            return

        # 启动共享服务
        self.share_btn.setEnabled(False)
        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.sharing_server.start_sharing(zip_path)
        QApplication.restoreOverrideCursor()

    def on_sharing_started(self, url):
        """共享服务启动后的回调"""
        # 显示分享对话框
        share_dialog = ShareDialog(url, self)
        share_dialog.exec_()

        # 更新状态栏
        self.sharing_label.setText(f'<a href="{url}">{url}</a>')
        self.sharing_label.show()
        self.stop_sharing_btn.show()

        # 自动复制URL到剪贴板
        clipboard = QApplication.clipboard()
        clipboard.setText(url)

    def on_sharing_stopped(self):
        """共享服务停止后的回调"""
        self.sharing_label.hide()
        self.stop_sharing_btn.hide()
        self.share_btn.setEnabled(True)

        QMessageBox.information(self, "共享已停止", "文件共享服务已停止")

    def import_from_url(self):
        """从URL导入题目"""
        url, ok = QInputDialog.getText(
            self, "从URL导入",
            "请输入共享的考题文件URL:",
            QLineEdit.Normal,
            "http://"
        )

        if not ok or not url:
            return

        # 显示进度对话框
        progress = QProgressDialog("正在从URL下载文件...", "取消", 0, 0, self)
        progress.setWindowTitle("导入进度")
        progress.setWindowModality(Qt.WindowModal)
        progress.show()

        try:
            save_dir = "./downloads/"
            filename = os.path.join(save_dir, os.path.basename(url))  # 提取文件名‌:ml-citation{ref="8" data="citationList"}
            os.makedirs(save_dir, exist_ok=True)
            try:
                urlretrieve(url, filename)  # 直接下载并保存‌:ml-citation{ref="4,8" data="citationList"}
                print(f"文件已保存至: {filename}")
            except Exception as e:
                print(f"下载失败: {e}")

            # 导入ZIP文件
            self.import_questions_from_zip(filename)

            progress.close()
            QMessageBox.information(self, "成功", "从URL导入题目成功!")
        except Exception as e:
            progress.close()
            QMessageBox.critical(self, "导入失败", f"从URL导入题目失败:\n{str(e)}")
        finally:
            # 清理临时文件
            if 'filename' in locals() and os.path.exists(filename):
                os.remove(filename)

    def export_questions_to_zip(self, zip_path):
        """导出所有题目到ZIP文件"""
        # 获取所有题目
        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM questions ORDER BY created_at DESC")
        questions = []
        for row in cursor.fetchall():
            questions.append({
                'id': row[0],
                'question_type': row[1],
                'content': row[2],
                'content_image': row[3],
                'difficulty': row[4],
                'tags': row[5],
                'category': row[6],
                'answer': row[7],
                'answer_image': row[8],
                'notes': row[9],
                'is_favorite': row[10]
            })
        conn.close()

        if not questions:
            QMessageBox.warning(self, "警告", "没有题目可导出!")
            return False

        # 创建临时目录
        temp_dir = os.path.join("temp", "export_" + str(uuid.uuid4())[:8])
        os.makedirs(temp_dir, exist_ok=True)
        csv_path = os.path.join(temp_dir, "questions_export.csv")
        image_dir = os.path.join(temp_dir, "images")
        os.makedirs(image_dir, exist_ok=True)

        # 写入CSV文件
        try:
            with open(csv_path, 'w', newline='', encoding='utf-8-sig') as csvfile:
                fieldnames = [
                    'id', 'question_type', 'content', 'content_image',
                    'difficulty', 'tags', 'category', 'answer',
                    'answer_image', 'notes', 'is_favorite'
                ]
                writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                writer.writeheader()

                # 处理图片并更新CSV中的路径
                for q in questions:
                    # 复制题目图片
                    if q['content_image'] and os.path.exists(q['content_image']):
                        ext = os.path.splitext(q['content_image'])[1]
                        new_path = os.path.join("images", f"{q['id']}_content{ext}")
                        shutil.copy2(q['content_image'], os.path.join(temp_dir, new_path))
                        q['content_image'] = new_path

                    # 复制答案图片
                    if q['answer_image'] and os.path.exists(q['answer_image']):
                        ext = os.path.splitext(q['answer_image'])[1]
                        new_path = os.path.join("images", f"{q['id']}_answer{ext}")
                        shutil.copy2(q['answer_image'], os.path.join(temp_dir, new_path))
                        q['answer_image'] = new_path

                    writer.writerow(q)
        except Exception as e:
            QMessageBox.critical(self, "导出失败", f"创建CSV文件失败: {str(e)}")
            shutil.rmtree(temp_dir, ignore_errors=True)
            return False

        # 创建ZIP文件
        try:
            with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                # 添加CSV文件
                zipf.write(csv_path, os.path.basename(csv_path))

                # 添加图片文件
                for root, _, files in os.walk(image_dir):
                    for file in files:
                        file_path = os.path.join(root, file)
                        arcname = os.path.relpath(file_path, temp_dir)
                        zipf.write(file_path, arcname)

            # 清理临时文件
            shutil.rmtree(temp_dir, ignore_errors=True)
            return True
        except Exception as e:
            QMessageBox.critical(self, "导出失败", f"创建ZIP文件失败: {str(e)}")
            shutil.rmtree(temp_dir, ignore_errors=True)
            return False

    def import_questions_from_zip(self, zip_path):
        """从ZIP文件导入题目"""
        # 创建临时目录
        temp_dir = os.path.join("temp", "import_" + str(uuid.uuid4())[:8])
        os.makedirs(temp_dir, exist_ok=True)

        # 解压ZIP文件
        try:
            with zipfile.ZipFile(zip_path, 'r') as zip_ref:
                zip_ref.extractall(temp_dir)
        except Exception as e:
            QMessageBox.critical(self, "导入失败", f"解压ZIP文件失败: {str(e)}")
            shutil.rmtree(temp_dir, ignore_errors=True)
            return False

        # 查找CSV文件
        csv_file = None
        for f in os.listdir(temp_dir):
            if f.lower().endswith('.csv'):
                csv_file = os.path.join(temp_dir, f)
                break

        if not csv_file:
            QMessageBox.critical(self, "导入失败", "ZIP文件中没有找到CSV文件")
            shutil.rmtree(temp_dir, ignore_errors=True)
            return False

        # 读取CSV文件
        try:
            with open(csv_file, 'r', encoding='utf-8-sig') as csvfile:
                reader = csv.DictReader(csvfile)
                questions = [row for row in reader]
        except Exception as e:
            QMessageBox.critical(self, "导入失败", f"读取CSV文件失败: {str(e)}")
            shutil.rmtree(temp_dir, ignore_errors=True)
            return False

        if not questions:
            QMessageBox.warning(self, "警告", "CSV文件中没有有效数据!")
            shutil.rmtree(temp_dir, ignore_errors=True)
            return False

        # 准备进度对话框
        progress = QProgressDialog("导入题目...", "取消", 0, len(questions), self)
        progress.setWindowTitle("导入进度")
        progress.setWindowModality(Qt.WindowModal)
        progress.show()

        conn = get_db_connection()
        cursor = conn.cursor()

        success_count = 0
        skip_count = 0
        error_count = 0

        for i, question in enumerate(questions):
            progress.setValue(i)
            QApplication.processEvents()

            if progress.wasCanceled():
                break

            try:
                # 检查是否已存在
                md5 = hashlib.md5((question['content'] + question['answer']).encode('utf-8')).hexdigest()
                cursor.execute("SELECT id FROM questions WHERE md5=?", (md5,))
                if cursor.fetchone():
                    skip_count += 1
                    continue

                # 处理图片路径
                content_image = ""
                if question['content_image']:
                    src_path = os.path.join(temp_dir, question['content_image'])
                    if os.path.exists(src_path):
                        # 创建目标目录
                        question_id = str(uuid.uuid4())
                        image_dir = os.path.join("data", "images", question_id)
                        os.makedirs(image_dir, exist_ok=True)

                        # 复制图片
                        ext = os.path.splitext(src_path)[1]
                        dst_path = os.path.join(image_dir, f"content{ext}")
                        shutil.copy2(src_path, dst_path)
                        content_image = dst_path

                answer_image = ""
                if question['answer_image']:
                    src_path = os.path.join(temp_dir, question['answer_image'])
                    if os.path.exists(src_path):
                        # 使用相同的question_id目录
                        if not content_image:  # 如果还没有创建目录
                            question_id = str(uuid.uuid4())
                            image_dir = os.path.join("data", "images", question_id)
                            os.makedirs(image_dir, exist_ok=True)

                        ext = os.path.splitext(src_path)[1]
                        dst_path = os.path.join(image_dir, f"answer{ext}")
                        shutil.copy2(src_path, dst_path)
                        answer_image = dst_path

                # 插入数据库
                cursor.execute('''
                    INSERT INTO questions (
                        id, question_type, content, content_image, difficulty, 
                        tags, category, answer, answer_image, notes, 
                        is_favorite, md5
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                ''', (
                    # question_id if 'question_id' in locals() else str(uuid.uuid4()),
                    question['id'],
                    question['question_type'],
                    question['content'],
                    content_image,
                    int(question.get('difficulty', 3)),
                    question['tags'],
                    question['category'],
                    question['answer'],
                    answer_image,
                    question.get('notes', ''),
                    int(question.get('is_favorite', 0)),
                    md5
                ))

                success_count += 1
            except Exception as e:
                error_count += 1
                print(f"导入题目失败: {question_id}")
                print(f"导入题目失败: {question['content']}")
                print(f"导入题目失败: {question['answer']}")
                print(f"导入题目失败: {str(e)}")

        conn.commit()
        conn.close()
        progress.close()

        # 清理临时文件
        shutil.rmtree(temp_dir, ignore_errors=True)

        # 显示导入结果
        QMessageBox.information(
            self, "导入完成",
            f"导入结果:\n成功: {success_count}\n跳过: {skip_count}\n失败: {error_count}"
        )

        # 刷新列表
        self.search_questions()
        self.load_categories()

        return True

    def load_categories(self):
        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT DISTINCT category FROM questions WHERE category != '' ORDER BY category")
        categories = [row[0] for row in cursor.fetchall()]
        conn.close()

        self.category_combo.clear()
        self.category_combo.addItem("所有分类", "")
        for category in categories:
            self.category_combo.addItem(category, category)

    def search_questions(self):
        search_text = self.search_edit.text().strip()
        question_type = self.type_combo.currentData()
        difficulty = self.difficulty_combo.currentData()
        category = self.category_combo.currentData()
        tags = self.tags_edit.text().strip()
        only_favorite = self.favorite_check.isChecked()

        # 构建查询条件和参数
        conditions = []
        params = []

        if search_text:
            conditions.append("content LIKE ?")
            params.append(f"%{search_text}%")

        if question_type:
            conditions.append("question_type = ?")
            params.append(question_type)

        if difficulty > 0:
            conditions.append("difficulty = ?")
            params.append(difficulty)

        if category:
            conditions.append("category = ?")
            params.append(category)

        if tags:
            tag_list = [tag.strip() for tag in tags.split(",") if tag.strip()]
            for tag in tag_list:
                conditions.append("tags LIKE ?")
                params.append(f"%{tag}%")

        if only_favorite:
            conditions.append("is_favorite = 1")

        # 计算总数
        count_query = "SELECT COUNT(*) FROM questions"
        if conditions:
            count_query += " WHERE " + " AND ".join(conditions)

        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute(count_query, params)
        self.total_records = cursor.fetchone()[0]

        # 计算分页
        self.page_size = int(self.page_size_combo.currentText())
        self.total_pages = max(1, (self.total_records + self.page_size - 1) // self.page_size)
        self.current_page = min(self.current_page, self.total_pages)

        # 查询数据
        query = "SELECT * FROM questions"
        if conditions:
            query += " WHERE " + " AND ".join(conditions)
        query += " ORDER BY created_at DESC LIMIT ? OFFSET ?"

        offset = (self.current_page - 1) * self.page_size
        params.extend([self.page_size, offset])

        cursor.execute(query, params)
        questions = []
        for row in cursor.fetchall():
            questions.append({
                'id': row[0],
                'question_type': row[1],
                'content': row[2],
                'content_image': row[3],
                'difficulty': row[4],
                'tags': row[5],
                'category': row[6],
                'answer': row[7],
                'answer_image': row[8],
                'notes': row[9],
                'is_favorite': row[10]
            })

        conn.close()

        # 更新表格
        self.table.setRowCount(0)
        for question in questions:
            self.table.add_question(question)

        # 更新分页信息
        self.update_pagination()

    def update_pagination(self):
        self.page_label.setText(f"{self.current_page}/{self.total_pages}")
        self.prev_btn.setEnabled(self.current_page > 1)
        self.next_btn.setEnabled(self.current_page < self.total_pages)

    def prev_page(self):
        if self.current_page > 1:
            self.current_page -= 1
            self.search_questions()

    def next_page(self):
        if self.current_page < self.total_pages:
            self.current_page += 1
            self.search_questions()

    def change_page_size(self):
        self.current_page = 1
        self.search_questions()

    def add_question(self):
        self.main_window.edit_widget.clear_form()  # 使用main_window引用
        self.main_window.show_edit()

    def edit_question(self):
        selected = self.table.selectedItems()
        if not selected:
            QMessageBox.warning(self, "警告", "请选择要编辑的题目!")
            return

        row = selected[0].row()
        question_id = self.table.item(row, 0).text()

        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM questions WHERE id=?", (question_id,))
        row = cursor.fetchone()
        conn.close()

        if row:
            question = {
                'id': row[0],
                'question_type': row[1],
                'content': row[2],
                'content_image': row[3],
                'difficulty': row[4],
                'tags': row[5],
                'category': row[6],
                'answer': row[7],
                'answer_image': row[8],
                'notes': row[9],
                'is_favorite': row[10]
            }

            self.main_window.edit_widget.load_question(question)  # 使用main_window引用
            self.main_window.show_edit()

    def delete_questions(self):
        selected = self.table.selectedItems()
        if not selected:
            QMessageBox.warning(self, "警告", "请选择要删除的题目!")
            return

        # 获取选中的所有行
        rows = set()
        for item in selected:
            rows.add(item.row())

        # 确认删除
        reply = QMessageBox.question(
            self, "确认删除",
            f"确定要删除选中的 {len(rows)} 道题目吗?",
            QMessageBox.Yes | QMessageBox.No
        )

        if reply == QMessageBox.No:
            return

        # 删除题目
        conn = get_db_connection()
        cursor = conn.cursor()

        for row in rows:
            question_id = self.table.item(row, 0).text()

            # 删除图片目录
            image_dir = os.path.join("data", "images", question_id)
            if os.path.exists(image_dir):
                shutil.rmtree(image_dir)

            # 删除数据库记录
            cursor.execute("DELETE FROM questions WHERE id=?", (question_id,))

        conn.commit()
        conn.close()

        QMessageBox.information(self, "成功", "题目删除成功!")
        self.search_questions()

    def export_questions(self):
        # 获取当前筛选条件
        search_text = self.search_edit.text().strip()
        question_type = self.type_combo.currentData()
        difficulty = self.difficulty_combo.currentData()
        category = self.category_combo.currentData()
        tags = self.tags_edit.text().strip()
        only_favorite = self.favorite_check.isChecked()

        # 构建查询条件
        conditions = []
        params = []

        if search_text:
            conditions.append("content LIKE ?")
            params.append(f"%{search_text}%")

        if question_type:
            conditions.append("question_type = ?")
            params.append(question_type)

        if difficulty > 0:
            conditions.append("difficulty = ?")
            params.append(difficulty)

        if category:
            conditions.append("category = ?")
            params.append(category)

        if tags:
            tag_list = [tag.strip() for tag in tags.split(",") if tag.strip()]
            for tag in tag_list:
                conditions.append("tags LIKE ?")
                params.append(f"%{tag}%")

        if only_favorite:
            conditions.append("is_favorite = 1")

        # 查询所有符合条件的题目
        query = "SELECT * FROM questions"
        if conditions:
            query += " WHERE " + " AND ".join(conditions)
        query += " ORDER BY created_at DESC"

        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute(query, params)
        questions = []
        for row in cursor.fetchall():
            questions.append({
                'id': row[0],
                'question_type': row[1],
                'content': row[2],
                'content_image': row[3],
                'difficulty': row[4],
                'tags': row[5],
                'category': row[6],
                'answer': row[7],
                'answer_image': row[8],
                'notes': row[9],
                'is_favorite': row[10]
            })

        conn.close()

        if not questions:
            QMessageBox.warning(self, "警告", "没有题目可导出!")
            return

        # 选择保存位置
        default_name = "questions_export"
        if search_text:
            default_name += f"_{search_text[:20]}"
        if question_type:
            default_name += f"_{question_type}"

        file_path, _ = QFileDialog.getSaveFileName(
            self, "导出题目",
            default_name,
            "CSV文件 (*.csv);;所有文件 (*)"
        )

        if not file_path:
            return

        # 确保文件扩展名是.csv
        if not file_path.lower().endswith('.csv'):
            file_path += '.csv'

        # 导出CSV
        try:
            with open(file_path, 'w', newline='', encoding='utf-8-sig') as csvfile:
                fieldnames = [
                    'id', 'question_type', 'content', 'content_image',
                    'difficulty', 'tags', 'category', 'answer',
                    'answer_image', 'notes', 'is_favorite'
                ]
                writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
                writer.writeheader()
                writer.writerows(questions)

            # 导出图片
            image_dir = os.path.splitext(file_path)[0] + "_images"
            if not os.path.exists(image_dir):
                os.makedirs(image_dir)

            for question in questions:
                qid = question['id']
                if question['content_image'] and os.path.exists(question['content_image']):
                    ext = os.path.splitext(question['content_image'])[1]
                    shutil.copy2(
                        question['content_image'],
                        os.path.join(image_dir, f"{qid}_content{ext}")
                    )

                if question['answer_image'] and os.path.exists(question['answer_image']):
                    ext = os.path.splitext(question['answer_image'])[1]
                    shutil.copy2(
                        question['answer_image'],
                        os.path.join(image_dir, f"{qid}_answer{ext}")
                    )

            # 创建压缩包
            zip_path = os.path.splitext(file_path)[0] + ".zip"
            with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
                zipf.write(file_path, os.path.basename(file_path))
                for root, _, files in os.walk(image_dir):
                    for file in files:
                        zipf.write(
                            os.path.join(root, file),
                            os.path.join("images", file)
                        )

            # 删除临时目录
            shutil.rmtree(image_dir)
            os.remove(file_path)

            QMessageBox.information(
                self, "导出成功",
                f"成功导出 {len(questions)} 道题目到 {zip_path}"
            )
        except Exception as e:
            QMessageBox.critical(
                self, "导出失败",
                f"导出过程中发生错误: {str(e)}"
            )

    def import_questions(self):
        file_path, _ = QFileDialog.getOpenFileName(
            self, "导入题目",
            "",
            "ZIP文件 (*.zip);;CSV文件 (*.csv);;所有文件 (*)"
        )

        if not file_path:
            return

        # 如果是ZIP文件，先解压
        temp_dir = None
        csv_path = file_path
        if file_path.lower().endswith('.zip'):
            try:
                temp_dir = os.path.join("temp", str(uuid.uuid4()))
                os.makedirs(temp_dir, exist_ok=True)

                with zipfile.ZipFile(file_path, 'r') as zipf:
                    # 查找CSV文件
                    csv_files = [f for f in zipf.namelist() if f.lower().endswith('.csv')]
                    if not csv_files:
                        raise ValueError("ZIP文件中没有找到CSV文件")

                    # 解压CSV文件
                    csv_filename = csv_files[0]
                    zipf.extract(csv_filename, temp_dir)
                    csv_path = os.path.join(temp_dir, csv_filename)

                    # 解压图片
                    image_dir = os.path.join(temp_dir, "images")
                    for file in zipf.namelist():
                        if file.startswith("images/") and not file.endswith("/"):
                            zipf.extract(file, temp_dir)
            except Exception as e:
                if temp_dir and os.path.exists(temp_dir):
                    shutil.rmtree(temp_dir)
                QMessageBox.critical(
                    self, "导入失败",
                    f"解压ZIP文件时发生错误: {str(e)}"
                )
                return

        # 读取CSV文件
        try:
            with open(csv_path, 'r', encoding='utf-8-sig') as csvfile:
                reader = csv.DictReader(csvfile)
                questions = [row for row in reader]

            if not questions:
                raise ValueError("CSV文件中没有题目数据")

            # 准备进度对话框
            progress = QProgressDialog("导入题目...", "取消", 0, len(questions), self)
            progress.setWindowTitle("导入进度")
            progress.setWindowModality(Qt.WindowModal)
            progress.show()

            # 导入到数据库
            conn = get_db_connection()
            cursor = conn.cursor()

            success_count = 0
            skip_count = 0
            error_count = 0

            for i, question in enumerate(questions):
                progress.setValue(i)
                QApplication.processEvents()

                if progress.wasCanceled():
                    break

                try:
                    # 检查是否已存在
                    cursor.execute("SELECT id FROM questions WHERE id=?", (question['id'],))
                    if cursor.fetchone():
                        skip_count += 1
                        continue

                    # 处理图片路径
                    content_image = question['content_image']
                    answer_image = question['answer_image']

                    if temp_dir and content_image:
                        image_path = os.path.join(temp_dir, "images",
                                                  f"{question['id']}_content{os.path.splitext(content_image)[1]}")
                        if os.path.exists(image_path):
                            # 创建目标目录
                            target_dir = os.path.join("data", "images", question['id'])
                            os.makedirs(target_dir, exist_ok=True)

                            # 复制图片
                            ext = os.path.splitext(image_path)[1]
                            new_path = os.path.join(target_dir, f"content{ext}")
                            shutil.copy2(image_path, new_path)
                            question['content_image'] = new_path
                        else:
                            question['content_image'] = ""

                    if temp_dir and answer_image:
                        image_path = os.path.join(temp_dir, "images",
                                                  f"{question['id']}_answer{os.path.splitext(answer_image)[1]}")
                        if os.path.exists(image_path):
                            # 创建目标目录
                            target_dir = os.path.join("data", "images", question['id'])
                            os.makedirs(target_dir, exist_ok=True)

                            # 复制图片
                            ext = os.path.splitext(image_path)[1]
                            new_path = os.path.join(target_dir, f"answer{ext}")
                            shutil.copy2(image_path, new_path)
                            question['answer_image'] = new_path
                        else:
                            question['answer_image'] = ""

                    # 插入数据库
                    cursor.execute('''
                        INSERT INTO questions (
                            id, question_type, content, content_image, difficulty, 
                            tags, category, answer, answer_image, notes, 
                            is_favorite, md5
                        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                    ''', (
                        question['id'], question['question_type'],
                        question['content'], question['content_image'],
                        int(question['difficulty']), question['tags'],
                        question['category'], question['answer'],
                        question['answer_image'], question['notes'],
                        int(question.get('is_favorite', 0)),
                        hashlib.md5((question['content'] + question['answer']).encode('utf-8')).hexdigest()
                    ))

                    success_count += 1
                except Exception as e:
                    error_count += 1
                    print(f"导入题目 {question['id']} 失败: {str(e)}")

            conn.commit()
            conn.close()

            progress.close()

            # 清理临时文件
            if temp_dir and os.path.exists(temp_dir):
                shutil.rmtree(temp_dir)

            QMessageBox.information(
                self, "导入完成",
                f"导入结果:\n成功: {success_count}\n跳过: {skip_count}\n失败: {error_count}"
            )

            # 刷新列表
            self.search_questions()
            self.load_categories()
        except Exception as e:
            if temp_dir and os.path.exists(temp_dir):
                shutil.rmtree(temp_dir)
            QMessageBox.critical(
                self, "导入失败",
                f"导入过程中发生错误: {str(e)}"
            )

    def backup_data(self):
        try:
            backup_file = backup_database()

            # 备份图片目录
            image_dir = os.path.join("data", "images")
            if os.path.exists(image_dir):
                backup_image_dir = os.path.join("backups", f"images_{os.path.basename(backup_file).replace('.db', '')}")
                shutil.make_archive(backup_image_dir, 'zip', image_dir)

            QMessageBox.information(
                self, "备份成功",
                f"数据库已备份到: {backup_file}\n图片已备份到: {backup_image_dir}.zip"
            )
        except Exception as e:
            QMessageBox.critical(
                self, "备份失败",
                f"备份过程中发生错误: {str(e)}"
            )

    def restore_data(self):
        # 选择备份文件
        backup_file, _ = QFileDialog.getOpenFileName(
            self, "选择备份文件",
            "backups",
            "数据库文件 (*.db);;所有文件 (*)"
        )

        if not backup_file:
            return

        # 确认恢复
        reply = QMessageBox.question(
            self, "确认恢复",
            "恢复将覆盖当前所有数据，是否继续?",
            QMessageBox.Yes | QMessageBox.No
        )

        if reply == QMessageBox.No:
            return

        # 恢复数据库
        try:
            success = restore_database(backup_file)
            if not success:
                raise Exception("恢复数据库失败")

            # 恢复图片
            image_backup = os.path.splitext(backup_file)[0] + "_images.zip"
            if os.path.exists(image_backup):
                image_dir = os.path.join("data", "images")
                if os.path.exists(image_dir):
                    shutil.rmtree(image_dir)

                with zipfile.ZipFile(image_backup, 'r') as zipf:
                    zipf.extractall(os.path.dirname(image_dir))

            QMessageBox.information(
                self, "恢复成功",
                "数据和图片已成功恢复!"
            )

            # 刷新列表
            self.search_questions()
            self.load_categories()
        except Exception as e:
            QMessageBox.critical(
                self, "恢复失败",
                f"恢复过程中发生错误: {str(e)}"
            )

    def export_all_questions(self):
        """导出所有试题"""
        # 显示导出对话框
        dialog = ExportDialog(self)
        dialog.load_categories(self.get_all_categories())

        if dialog.exec_() != QDialog.Accepted:
            return

        settings = dialog.get_export_settings()

        # todo 过滤条件没生效 获取筛选后的题目
        questions = self.get_filtered_questions(settings['filter'])

        if not questions:
            QMessageBox.warning(self, "警告", "没有找到符合条件的题目!")
            return

        # 选择保存位置
        default_name = "questions_export"
        if settings['filter']['question_type']:
            default_name += f"_{settings['filter']['question_type']}"

        file_path, _ = QFileDialog.getSaveFileName(
            self, "导出试题",
            default_name,
            f"{settings['options']['format'].upper()} 文件 (*.{settings['options']['format']})"
        )

        if not file_path:
            return

        # 确保文件扩展名正确
        if not file_path.lower().endswith(f".{settings['options']['format']}"):
            file_path += f".{settings['options']['format']}"

        # 根据格式导出
        try:
            if settings['options']['format'] == "docx":
                self.export_to_docx(questions, file_path, settings['options'])
            elif settings['options']['format'] == "pdf":
                self.export_to_pdf(questions, file_path, settings['options'])
            elif settings['options']['format'] == "md":
                self.export_to_markdown(questions, file_path, settings['options'])

            QMessageBox.information(self, "成功", f"成功导出 {len(questions)} 道题目到 {file_path}")
        except Exception as e:
            QMessageBox.critical(self, "导出失败", f"导出过程中发生错误: {str(e)}")

    def get_all_categories(self):
        """获取所有分类"""
        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute("SELECT DISTINCT category FROM questions WHERE category != '' ORDER BY category")
        categories = [row[0] for row in cursor.fetchall()]
        conn.close()
        return categories

    def get_filtered_questions(self, filter_params):
        """根据筛选条件获取题目"""
        conditions = []
        params = []

        if filter_params['question_type']:
            conditions.append("question_type = ?")
            params.append(filter_params['question_type'])

        if filter_params['difficulty'] > 0:
            conditions.append("difficulty = ?")
            params.append(filter_params['difficulty'])

        if filter_params['category']:
            conditions.append("category = ?")
            params.append(filter_params['category'])

        if filter_params['tags']:
            tag_list = [tag.strip() for tag in filter_params['tags'].split(",") if tag.strip()]
            for tag in tag_list:
                conditions.append("tags LIKE ?")
                params.append(f"%{tag}%")

        if filter_params['only_favorite']:
            conditions.append("is_favorite = 1")

        query = "SELECT * FROM questions"
        if conditions:
            query += " WHERE " + " AND ".join(conditions)
        query += " ORDER BY created_at DESC"

        conn = get_db_connection()
        cursor = conn.cursor()
        cursor.execute(query, params)

        questions = []
        for row in cursor.fetchall():
            questions.append({
                'id': row[0],
                'question_type': row[1],
                'content': row[2],
                'content_image': row[3],
                'difficulty': row[4],
                'tags': row[5],
                'category': row[6],
                'answer': row[7],
                'answer_image': row[8],
                'notes': row[9],
                'is_favorite': row[10]
            })

        conn.close()
        return questions

    def export_to_docx(self, questions, file_path, options):
        """导出为Word文档"""
        doc = Document()
        # 获取默认样式并设置中文字体
        style = doc.styles['Normal']
        font = style.font
        font.name = 'SimSun'  # 西文字体名称
        font.element.rPr.rFonts.set(qn('w:eastAsia'), 'SimSun')

        doc.add_heading('试题导出', level=1)

        for i, question in enumerate(questions, 1):
            # 添加题目
            doc.add_heading(f"题目 {i}", level=2)
            doc.add_paragraph(f"类型:{question['question_type']}")
            # doc.add_paragraph(f"    {question['question_type']}")
            doc.add_paragraph(f"难度:{'★' * question['difficulty']}")
            # doc.add_paragraph(f"    {'★' * question['difficulty']}")
            if question['category']:
                doc.add_paragraph(f"分类:{question['category']}")
                # doc.add_paragraph(f"    {question['category']}")
                # doc.add_paragraph(f"分类: {question['category']}")
            if question['tags']:
                doc.add_paragraph(f"标签:{question['tags']}")
                # doc.add_paragraph(f"    {question['tags']}")

            # 题目内容
            doc.add_paragraph("题目内容:")
            doc.add_paragraph(f"    {question['content']}")

            # 题目图片
            if options['include_images'] and question['content_image'] and os.path.exists(question['content_image']):
                doc.add_picture(question['content_image'], width=Inches(4.0))

            # 答案
            if options['include_answers']:
                doc.add_paragraph("答案:")
                if question['question_type'] == "填空题":
                    answers = question['answer'].split("|")
                    for j, answer in enumerate(answers, 1):
                        doc.add_paragraph(f"{j}. {answer}")
                elif question['question_type'] == "选择题":
                    parts = question['answer'].split("|")
                    if len(parts) > 1:
                        options_text = "\n".join([f"{chr(65 + i)}. {option}" for i, option in enumerate(parts[:-1])])
                        doc.add_paragraph(options_text)
                        doc.add_paragraph(f"正确答案: {parts[-1]}")
                else:
                    doc.add_paragraph(question['answer'])

                # 答案图片
                if options['include_images'] and question['answer_image'] and os.path.exists(question['answer_image']):
                    doc.add_picture(question['answer_image'], width=Inches(4.0))

            # 备注
            if question['notes']:
                doc.add_paragraph(f"备注: {question['notes']}")

            doc.add_page_break()

        doc.save(file_path)

    def export_to_pdf(self, questions, file_path, options):
        """导出为 PDF 格式"""
        # 创建 QTextDocument 并填充内容
        doc = QTextDocument()
        html_content = ""

        for idx, question in enumerate(questions, start=1):
            html_content += f"<h2>第 {idx} 题</h2>"
            html_content += f"<p><b>类型：</b>{question['question_type']}</p>"
            html_content += f"<p><b>难度：</b>{'★' * question['difficulty']}</p>"
            html_content += f"<p><b>分类：</b>{question['category']}</p>"
            html_content += f"<p><b>标签：</b>{question['tags']}</p>"
            html_content += f"<p><b>收藏：</b>{'是' if question['is_favorite'] else '否'}</p>"

            # 题目内容
            html_content += f"<p><b>题目内容：</b>{question['content']}</p>"

            # 题目图片
            if question['content_image'] and os.path.exists(question['content_image']):
                html_content += f'<img src="{question["content_image"]}" width="300">'

            # 答案
            if options['include_answers']:
                html_content += f"<p><b>答案：</b></p>"
                if question['question_type'] == "填空题":
                    answers = question['answer'].split("|")
                    for j, answer in enumerate(answers, 1):
                        html_content += f"<p>{j}. {answer}</p>"
                elif question['question_type'] == "选择题":
                    parts = question['answer'].split("|")
                    if len(parts) > 1:
                        options = [f"{chr(65 + i)}. {opt}" for i, opt in enumerate(parts[:-1])]
                        html_content += "<p>" + "<br>".join(options) + "</p>"
                        html_content += f"<p><b>正确答案：</b>{parts[-1]}</p>"
                else:
                    html_content += f"<p>{question['answer']}</p>"

                # 答案图片
                if question['answer_image'] and os.path.exists(question['answer_image']):
                    html_content += f'<img src="{question["answer_image"]}" width="300">'
            else:
                if question['question_type'] == "综合题":
                    html_content += "<p><b>答案：</b><textarea style='width: 100%; height: 200px;' placeholder='请在此处作答'></textarea></p>"
                else:
                    html_content += "<p><b>答案：</b></p>"

            # 备注
            if question['notes']:
                html_content += f"<p><b>备注：</b>{question['notes']}</p>"

            html_content += "<p>&nbsp;</p>"  # 添加换行

        doc.setHtml(html_content)

        # 导出为 PDF
        printer = QPrinter(QPrinter.HighResolution)
        printer.setOutputFormat(QPrinter.PdfFormat)
        printer.setOutputFileName(file_path)
        doc.print_(printer)

        QMessageBox.information(self, "成功", f"试题已导出为 PDF 文件：{file_path}")

    def export_to_markdown(self, questions, file_path, options):
        """导出为Markdown文档"""
        md_content = "# 试题导出\n\n"
        output_dir = os.path.dirname(file_path)
        imgs_dir = os.path.join(output_dir, "imgs")
        os.makedirs(imgs_dir, exist_ok=True)

        for i, question in enumerate(questions, 1):
            md_content += f"## 题目 {i}\n\n"
            md_content += f"- **类型**: {question['question_type']}\n"
            md_content += f"- **难度**: {'★' * question['difficulty']}\n"

            if question['category']:
                md_content += f"- **分类**: {question['category']}\n"
            if question['tags']:
                md_content += f"- **标签**: {question['tags']}\n"

            md_content += "\n**题目内容**:\n\n"
            md_content += f"{question['content']}\n\n"
            if question['question_type'] == "选择题":
                parts = question['answer'].split("|")
                if len(parts) > 1:
                    for i, option in enumerate(parts[:-1]):
                        md_content += f"{chr(65 + i)}. {option}\n"

            # 创建题目特定的图片目录
            question_dir = os.path.join(imgs_dir, question['id'])
            os.makedirs(question_dir, exist_ok=True)

            # 题目图片
            if options['include_images'] and question['content_image'] and os.path.exists(question['content_image']):
                img_filename = os.path.basename(question['content_image'])
                dest_img_path = os.path.join(question_dir, img_filename)
                shutil.copy2(question['content_image'], dest_img_path)
                md_content += f"![题目图片](imgs/{question['id']}/{img_filename})\n\n"

            # 答案
            if options['include_answers']:
                md_content += "**答案**:\n\n"
                if question['question_type'] == "填空题":
                    answers = question['answer'].split("|")
                    for j, answer in enumerate(answers, 1):
                        md_content += f"{j}. {answer}\n"
                elif question['question_type'] == "选择题":
                    parts = question['answer'].split("|")
                    if len(parts) > 1:
                        # for i, option in enumerate(parts[:-1]):
                        #     md_content += f"{chr(65 + i)}. {option}\n"
                        md_content += f"\n正确答案: {parts[-1]}\n"
                else:
                    md_content += f"{question['answer']}\n"

                md_content += "\n"

                # 答案图片
                if options['include_images'] and question['answer_image'] and os.path.exists(question['answer_image']):
                    img_filename = os.path.basename(question['answer_image'])
                    dest_img_path = os.path.join(question_dir, img_filename)
                    shutil.copy2(question['answer_image'], dest_img_path)
                    md_content += f"![答案图片](imgs/{question['id']}/{img_filename})\n\n"

            # 备注
            if question['notes']:
                md_content += f"**备注**: {question['notes']}\n\n"

            md_content += "---\n\n"

        # 保存Markdown文件
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(md_content)

    def wrap_text(self, text, max_length):
        """将长文本换行"""
        words = text.split()
        lines = []
        current_line = []
        current_length = 0

        for word in words:
            if current_length + len(word) + 1 > max_length:
                lines.append(' '.join(current_line))
                current_line = [word]
                current_length = len(word)
            else:
                current_line.append(word)
                current_length += len(word) + 1

        if current_line:
            lines.append(' '.join(current_line))

        return lines


class QuestionDetailDialog(QDialog):
    def __init__(self, question_data, parent=None):
        super().__init__(parent)
        self.setWindowTitle("题目详情")
        self.setMinimumSize(600, 600)
        self.setup_ui(question_data)

    def setup_ui(self, q):
        # 创建滚动区域
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)

        # 创建内容容器
        content_widget = QWidget()
        scroll.setWidget(content_widget)

        # 主布局
        main_layout = QVBoxLayout(self)
        main_layout.addWidget(scroll)

        # 内容布局
        layout = QVBoxLayout(content_widget)
        layout.setContentsMargins(20, 20, 20, 20)

        # 基本信息区域（保持原有结构）
        info_layout = QFormLayout()
        info_layout.addRow("类型:", QLabel(q['question_type']))
        info_layout.addRow("难度:", QLabel('★' * q['difficulty']))
        info_layout.addRow("分类:", QLabel(q['category']))
        info_layout.addRow("标签:", QLabel(q['tags']))
        info_layout.addRow("收藏:", QLabel("是" if q['is_favorite'] else "否"))
        layout.addLayout(info_layout)

        # 添加分隔线
        layout.addWidget(self.create_horizontal_line())

        # 题目内容区域
        content_group = QGroupBox("题目内容")
        content_layout = QVBoxLayout()
        self.content_label = QLabel(q['content'])
        self.content_label.setWordWrap(True)
        self.content_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
        content_layout.addWidget(self.content_label)
        if q['question_type'] == "选择题":
            parts = q['answer'].split('|')
            if len(parts) > 1:
                options = [f"{chr(65 + i)}. {opt}" for i, opt in enumerate(parts[:-1])]
                content_layout.addWidget(QLabel('\n'.join(options)))

        # 图片显示（添加动态缩放）
        self.content_image_label = QLabel()
        self.content_image_label.setAlignment(Qt.AlignCenter)
        if q['content_image'] and os.path.exists(q['content_image']):
            pixmap = QPixmap(q['content_image'])
            scaled_pixmap = pixmap.scaled(500, 400, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            self.content_image_label.setPixmap(scaled_pixmap)
            self.content_image_label.setFixedSize(scaled_pixmap.size())
        content_layout.addWidget(self.content_image_label)
        content_group.setLayout(content_layout)
        layout.addWidget(content_group)

        # 答案区域
        answer_group = QGroupBox("答案及解析")
        answer_layout = QVBoxLayout()

        # 答案文本区域（添加滚动）
        answer_text_widget = QWidget()
        answer_scroll = QScrollArea()
        answer_scroll.setWidgetResizable(True)
        answer_scroll.setWidget(answer_text_widget)
        answer_text_layout = QVBoxLayout(answer_text_widget)

        # 根据题型处理答案
        if q['question_type'] == "选择题":
            parts = q['answer'].split('|')
            if len(parts) > 1:
                options = [f"{chr(65 + i)}. {opt}" for i, opt in enumerate(parts[:-1])]
                # answer_text_layout.addWidget(QLabel('\n'.join(options)))
                answer_text_layout.addWidget(QLabel(f"\n正确答案：{parts[-1]}"))
        elif q['question_type'] == "填空题":
            answers = q['answer'].split('|')
            answer_text_layout.addWidget(QLabel("填空答案：\n" + '\n'.join(
                [f"{i + 1}. {ans}" for i, ans in enumerate(answers)])))
        else:
            answer_label = QLabel(q['answer'])
            answer_label.setTextInteractionFlags(Qt.TextSelectableByMouse)
            answer_label.setWordWrap(True)
            answer_text_layout.addWidget(answer_label)

        # 答案图片
        self.answer_image_label = QLabel()
        self.answer_image_label.setAlignment(Qt.AlignCenter)
        if q['answer_image'] and os.path.exists(q['answer_image']):
            pixmap = QPixmap(q['answer_image'])
            scaled_pixmap = pixmap.scaled(500, 400, Qt.KeepAspectRatio, Qt.SmoothTransformation)
            self.answer_image_label.setPixmap(scaled_pixmap)
            self.answer_image_label.setFixedSize(scaled_pixmap.size())
        answer_text_layout.addWidget(self.answer_image_label)

        # 备注
        if q['notes']:
            notes_label = QLabel(f"备注：{q['notes']}")
            notes_label.setWordWrap(True)
            answer_text_layout.addWidget(notes_label)

        answer_layout.addWidget(answer_scroll)
        answer_group.setLayout(answer_layout)
        layout.addWidget(answer_group)

        # 底部按钮
        btn_layout = QHBoxLayout()
        close_btn = QPushButton("关闭")
        close_btn.clicked.connect(self.close)
        btn_layout.addStretch()
        btn_layout.addWidget(close_btn)
        layout.addLayout(btn_layout)

        # 设置内容区域的最小尺寸
        content_widget.setMinimumSize(700, 800)

    def create_horizontal_line(self):
        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)
        return line
